package com.itheima.reggie.common;

import com.itheima.reggie.entity.Children;
import org.reflections.Reflections;
import org.springframework.web.bind.annotation.*;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

public class Reflection {
    public static List<Children> getReflections() {
        // 获取com.itheima.reggie包路径下面的资源
        Reflections reflections = new Reflections("com.itheima.reggie");
        // 获取使用了@RestController 注解的类
        Set<Class<?>> typesAnnotatedWith = reflections.getTypesAnnotatedWith(RestController.class);
        //存放该员工的权限信息
        List<Children> childrenList = new ArrayList<>();

        //遍历每个 Controller 类
        for (Class<?> cls : typesAnnotatedWith) {
            // 获取完整的类名称，比如: com.itheima.reggie.controller.AdressController
            String name = cls.getName();
            // 对名称进行裁剪，只要有用部分，比如：AddressController
            name = name.substring(name.lastIndexOf(".") + 1);
            // 因为类上面 会放置公共路径，比如 @RequestMapping("/address")，所以需要解析 并获取到RequestMapping 注解
            //获取类上的访问路径
            RequestMapping clsRequestMapping = cls.getAnnotation(RequestMapping.class);
            // basePath 用来记录请求的公共部分，先置空，有些类没有公共部分
            String basePath = "";
            //如果类上有公共访问路径
            if (clsRequestMapping != null) {
                // 获取 requestMapping的 资源路径，即value，设置的访问路径是设置成员value的值
                String[] clsValues = clsRequestMapping.value();
                // 如果value有值，那么这部分就是 公共的资源路径
                if (clsValues != null && clsValues.length > 0) {
                    basePath = clsValues[0];
                }
            }

            //通过反射，获取到类中的所有方法
            Method[] methods = cls.getMethods();
            //存放一个Controller类里的信息
            Children children = new Children();
            //作为暂存的集合，后续设置其到 children对象 的children成员属性中去
            List<Children> list = new ArrayList<>();
            //遍历类中所有方法，将方法上的访问路径和访问方法，同类访问路径进行拼接
            for (Method method : methods) {
                //方法上只加了确定访问方法的注解,所以第0个，就是该方法的访问方式
                String methodType = null;
                String childPath = null;

                // 判断方法是否有 RequestMapping 注解，有的话，解析获取 value和method
                if (method.isAnnotationPresent(RequestMapping.class)) {

                    RequestMapping nowAnnotation = method.getAnnotation(RequestMapping.class);
                    RequestMethod[] requestMethods = nowAnnotation.method();
                    String[] methodValues = nowAnnotation.value();

                    if (methodValues != null && methodValues.length > 0) {
                        childPath = methodValues[0];
                    }

                    if (requestMethods != null && requestMethods.length > 0) {
                        methodType = requestMethods[0].name().toUpperCase();
                    }

                    // 判断方法是否有 GetMapping 注解，有的话，解析获取 value和method
                } else if (method.isAnnotationPresent(GetMapping.class)) {

                    methodType = "GET";
                    GetMapping nowAnnotation = method.getAnnotation(GetMapping.class);
                    String[] methodValues = nowAnnotation.value();

                    if (methodValues != null && methodValues.length > 0) {
                        childPath = methodValues[0];
                    }

                } else if (method.isAnnotationPresent(PostMapping.class)) {

                    methodType = "POST";
                    PostMapping nowAnnotation = method.getAnnotation(PostMapping.class);
                    String[] methodValues = nowAnnotation.value();

                    if (methodValues != null && methodValues.length > 0) {
                        childPath = methodValues[0];
                    }

                } else if (method.isAnnotationPresent(PutMapping.class)) {

                    methodType = "PUT";
                    PutMapping nowAnnotation = method.getAnnotation(PutMapping.class);
                    String[] methodValues = nowAnnotation.value();

                    if (methodValues != null && methodValues.length > 0) {
                        childPath = methodValues[0];
                    }

                } else if (method.isAnnotationPresent(DeleteMapping.class)) {

                    methodType = "DELETE";
                    DeleteMapping nowAnnotation = method.getAnnotation(DeleteMapping.class);
                    String[] methodValues = nowAnnotation.value();

                    if (methodValues != null && methodValues.length > 0) {
                        childPath = methodValues[0];
                    }

                }

                // 构建这个方法的 Children
                if (childPath == null && methodType == null) {
                    continue;
                } else {
                    if (childPath == null) {
                        childPath = "";
                    } else if (!childPath.startsWith("/")) {//如果注解的value值，第一个字符不是“/”符号，那么就拼接上“/”
                        childPath = "/" + childPath;
                    }
                }
                //存放每个方法的信息
                Children methodInfo = new Children();
                methodInfo.setId( methodType + " " + basePath + childPath);
                methodInfo.setLabel(methodType + " " + basePath + childPath);
                //将方法信息暂存到list集合中
                list.add(methodInfo);
            }
            //设置每个 Controller的信息进入 Data 变量中
            children.setId("PID::" + name);
            children.setLabel(name);
            //将该类中暂存在 list集合 中所有类的信息设置进保存类信息的 对象中
            children.setChildren(list);
            //将该 Controller类 的信息存入 保存所有信息的集合 中
            childrenList.add(children);
        }
        return childrenList;
    }
}
